@sentryware/s2-node 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +45 -0
- package/.dockerignore +1 -0
- package/.gitmodules +3 -0
- package/CHANGELOG.md +33 -0
- package/LICENSE +201 -0
- package/README.md +147 -0
- package/binding.gyp +170 -0
- package/docker/Dockerfile.node20.test +8 -0
- package/docker/Dockerfile.node22.test +8 -0
- package/docker/Dockerfile.node24.test +8 -0
- package/index.d.ts +117 -0
- package/index.js +6 -0
- package/jest.config.js +184 -0
- package/package.json +43 -0
- package/publish-linux.sh +18 -0
- package/publish-osx.sh +19 -0
- package/src/builder.cc +84 -0
- package/src/builder.h +29 -0
- package/src/cell.cc +71 -0
- package/src/cell.h +26 -0
- package/src/cell_id.cc +210 -0
- package/src/cell_id.h +44 -0
- package/src/cell_union.cc +237 -0
- package/src/cell_union.h +34 -0
- package/src/earth.cc +185 -0
- package/src/earth.h +33 -0
- package/src/latlng.cc +132 -0
- package/src/latlng.h +28 -0
- package/src/loop.cc +51 -0
- package/src/loop.h +21 -0
- package/src/point.cc +69 -0
- package/src/point.h +23 -0
- package/src/polygon.cc +36 -0
- package/src/polygon.h +20 -0
- package/src/polyline.cc +186 -0
- package/src/polyline.h +34 -0
- package/src/region_coverer.cc +450 -0
- package/src/region_coverer.h +56 -0
- package/src/s2.cc +27 -0
- package/test/Cell.test.js +37 -0
- package/test/CellId.test.js +135 -0
- package/test/CellUnion.test.js +150 -0
- package/test/Earth.test.js +62 -0
- package/test/LatLng.test.js +45 -0
- package/test/Point.test.js +14 -0
- package/test/Polyline.test.js +78 -0
- package/test/RegionCoverer.test.js +301 -0
- package/test.sh +16 -0
- package/third_party/s2geometry/.travis.yml +163 -0
- package/third_party/s2geometry/AUTHORS +13 -0
- package/third_party/s2geometry/CONTRIBUTING.md +65 -0
- package/third_party/s2geometry/CONTRIBUTORS +30 -0
- package/third_party/s2geometry/LICENSE +202 -0
- package/third_party/s2geometry/NOTICE +5 -0
- package/third_party/s2geometry/README.md +127 -0
- package/third_party/s2geometry/doc/examples/point_index.cc +44 -0
- package/third_party/s2geometry/doc/examples/term_index.cc +99 -0
- package/third_party/s2geometry/doc/examples/term_index.py +101 -0
- package/third_party/s2geometry/src/python/coder.i +125 -0
- package/third_party/s2geometry/src/python/pywraps2_test.py +786 -0
- package/third_party/s2geometry/src/python/s2.i +37 -0
- package/third_party/s2geometry/src/python/s2_common.i +756 -0
- package/third_party/s2geometry/src/s2/_fp_contract_off.h +60 -0
- package/third_party/s2geometry/src/s2/base/casts.h +318 -0
- package/third_party/s2geometry/src/s2/base/commandlineflags.h +67 -0
- package/third_party/s2geometry/src/s2/base/integral_types.h +31 -0
- package/third_party/s2geometry/src/s2/base/log_severity.h +40 -0
- package/third_party/s2geometry/src/s2/base/logging.h +173 -0
- package/third_party/s2geometry/src/s2/base/mutex.h +61 -0
- package/third_party/s2geometry/src/s2/base/port.h +999 -0
- package/third_party/s2geometry/src/s2/base/spinlock.h +60 -0
- package/third_party/s2geometry/src/s2/base/stringprintf.cc +107 -0
- package/third_party/s2geometry/src/s2/base/stringprintf.h +53 -0
- package/third_party/s2geometry/src/s2/base/strtoint.cc +65 -0
- package/third_party/s2geometry/src/s2/base/strtoint.h +106 -0
- package/third_party/s2geometry/src/s2/base/timer.h +50 -0
- package/third_party/s2geometry/src/s2/encoded_s2cell_id_vector.cc +164 -0
- package/third_party/s2geometry/src/s2/encoded_s2cell_id_vector.h +110 -0
- package/third_party/s2geometry/src/s2/encoded_s2cell_id_vector_test.cc +232 -0
- package/third_party/s2geometry/src/s2/encoded_s2point_vector.cc +838 -0
- package/third_party/s2geometry/src/s2/encoded_s2point_vector.h +140 -0
- package/third_party/s2geometry/src/s2/encoded_s2point_vector_test.cc +344 -0
- package/third_party/s2geometry/src/s2/encoded_s2shape_index.cc +181 -0
- package/third_party/s2geometry/src/s2/encoded_s2shape_index.h +276 -0
- package/third_party/s2geometry/src/s2/encoded_s2shape_index_test.cc +244 -0
- package/third_party/s2geometry/src/s2/encoded_string_vector.cc +66 -0
- package/third_party/s2geometry/src/s2/encoded_string_vector.h +164 -0
- package/third_party/s2geometry/src/s2/encoded_string_vector_test.cc +69 -0
- package/third_party/s2geometry/src/s2/encoded_uint_vector.h +299 -0
- package/third_party/s2geometry/src/s2/encoded_uint_vector_test.cc +124 -0
- package/third_party/s2geometry/src/s2/id_set_lexicon.cc +81 -0
- package/third_party/s2geometry/src/s2/id_set_lexicon.h +199 -0
- package/third_party/s2geometry/src/s2/id_set_lexicon_test.cc +70 -0
- package/third_party/s2geometry/src/s2/mutable_s2shape_index.cc +1585 -0
- package/third_party/s2geometry/src/s2/mutable_s2shape_index.h +600 -0
- package/third_party/s2geometry/src/s2/mutable_s2shape_index_test.cc +589 -0
- package/third_party/s2geometry/src/s2/r1interval.h +220 -0
- package/third_party/s2geometry/src/s2/r1interval_test.cc +185 -0
- package/third_party/s2geometry/src/s2/r2.h +26 -0
- package/third_party/s2geometry/src/s2/r2rect.cc +93 -0
- package/third_party/s2geometry/src/s2/r2rect.h +234 -0
- package/third_party/s2geometry/src/s2/r2rect_test.cc +228 -0
- package/third_party/s2geometry/src/s2/s1angle.cc +54 -0
- package/third_party/s2geometry/src/s2/s1angle.h +336 -0
- package/third_party/s2geometry/src/s2/s1angle_test.cc +185 -0
- package/third_party/s2geometry/src/s2/s1chord_angle.cc +159 -0
- package/third_party/s2geometry/src/s2/s1chord_angle.h +369 -0
- package/third_party/s2geometry/src/s2/s1chord_angle_test.cc +207 -0
- package/third_party/s2geometry/src/s2/s1interval.cc +296 -0
- package/third_party/s2geometry/src/s2/s1interval.h +266 -0
- package/third_party/s2geometry/src/s2/s1interval_test.cc +469 -0
- package/third_party/s2geometry/src/s2/s2boolean_operation.cc +2391 -0
- package/third_party/s2geometry/src/s2/s2boolean_operation.h +501 -0
- package/third_party/s2geometry/src/s2/s2boolean_operation_test.cc +1400 -0
- package/third_party/s2geometry/src/s2/s2builder.cc +1828 -0
- package/third_party/s2geometry/src/s2/s2builder.h +1057 -0
- package/third_party/s2geometry/src/s2/s2builder_graph.cc +1084 -0
- package/third_party/s2geometry/src/s2/s2builder_graph.h +799 -0
- package/third_party/s2geometry/src/s2/s2builder_graph_test.cc +462 -0
- package/third_party/s2geometry/src/s2/s2builder_layer.h +50 -0
- package/third_party/s2geometry/src/s2/s2builder_test.cc +1329 -0
- package/third_party/s2geometry/src/s2/s2builderutil_closed_set_normalizer.cc +313 -0
- package/third_party/s2geometry/src/s2/s2builderutil_closed_set_normalizer.h +221 -0
- package/third_party/s2geometry/src/s2/s2builderutil_closed_set_normalizer_test.cc +261 -0
- package/third_party/s2geometry/src/s2/s2builderutil_find_polygon_degeneracies.cc +392 -0
- package/third_party/s2geometry/src/s2/s2builderutil_find_polygon_degeneracies.h +86 -0
- package/third_party/s2geometry/src/s2/s2builderutil_find_polygon_degeneracies_test.cc +182 -0
- package/third_party/s2geometry/src/s2/s2builderutil_graph_shape.h +57 -0
- package/third_party/s2geometry/src/s2/s2builderutil_lax_polygon_layer.cc +212 -0
- package/third_party/s2geometry/src/s2/s2builderutil_lax_polygon_layer.h +218 -0
- package/third_party/s2geometry/src/s2/s2builderutil_lax_polygon_layer_test.cc +367 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2point_vector_layer.cc +74 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2point_vector_layer.h +122 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2point_vector_layer_test.cc +167 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polygon_layer.cc +191 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polygon_layer.h +211 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polygon_layer_test.cc +312 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_layer.cc +105 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_layer.h +174 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_layer_test.cc +220 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_vector_layer.cc +98 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_vector_layer.h +292 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_vector_layer_test.cc +233 -0
- package/third_party/s2geometry/src/s2/s2builderutil_snap_functions.cc +354 -0
- package/third_party/s2geometry/src/s2/s2builderutil_snap_functions.h +239 -0
- package/third_party/s2geometry/src/s2/s2builderutil_snap_functions_test.cc +716 -0
- package/third_party/s2geometry/src/s2/s2builderutil_testing.cc +37 -0
- package/third_party/s2geometry/src/s2/s2builderutil_testing.h +100 -0
- package/third_party/s2geometry/src/s2/s2builderutil_testing_test.cc +85 -0
- package/third_party/s2geometry/src/s2/s2cap.cc +347 -0
- package/third_party/s2geometry/src/s2/s2cap.h +286 -0
- package/third_party/s2geometry/src/s2/s2cap_test.cc +379 -0
- package/third_party/s2geometry/src/s2/s2cell.cc +552 -0
- package/third_party/s2geometry/src/s2/s2cell.h +249 -0
- package/third_party/s2geometry/src/s2/s2cell_id.cc +619 -0
- package/third_party/s2geometry/src/s2/s2cell_id.h +705 -0
- package/third_party/s2geometry/src/s2/s2cell_id_test.cc +633 -0
- package/third_party/s2geometry/src/s2/s2cell_index.cc +149 -0
- package/third_party/s2geometry/src/s2/s2cell_index.h +660 -0
- package/third_party/s2geometry/src/s2/s2cell_index_test.cc +411 -0
- package/third_party/s2geometry/src/s2/s2cell_test.cc +687 -0
- package/third_party/s2geometry/src/s2/s2cell_union.cc +515 -0
- package/third_party/s2geometry/src/s2/s2cell_union.h +399 -0
- package/third_party/s2geometry/src/s2/s2cell_union_test.cc +598 -0
- package/third_party/s2geometry/src/s2/s2centroids.cc +84 -0
- package/third_party/s2geometry/src/s2/s2centroids.h +87 -0
- package/third_party/s2geometry/src/s2/s2centroids_test.cc +82 -0
- package/third_party/s2geometry/src/s2/s2closest_cell_query.cc +123 -0
- package/third_party/s2geometry/src/s2/s2closest_cell_query.h +385 -0
- package/third_party/s2geometry/src/s2/s2closest_cell_query_base.h +841 -0
- package/third_party/s2geometry/src/s2/s2closest_cell_query_base_test.cc +63 -0
- package/third_party/s2geometry/src/s2/s2closest_cell_query_test.cc +412 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query.cc +106 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query.h +421 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query_base.h +946 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query_base_test.cc +59 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query_test.cc +505 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query_testing.h +91 -0
- package/third_party/s2geometry/src/s2/s2closest_point_query.cc +66 -0
- package/third_party/s2geometry/src/s2/s2closest_point_query.h +465 -0
- package/third_party/s2geometry/src/s2/s2closest_point_query_base.h +767 -0
- package/third_party/s2geometry/src/s2/s2closest_point_query_base_test.cc +63 -0
- package/third_party/s2geometry/src/s2/s2closest_point_query_test.cc +312 -0
- package/third_party/s2geometry/src/s2/s2contains_point_query.h +328 -0
- package/third_party/s2geometry/src/s2/s2contains_point_query_test.cc +159 -0
- package/third_party/s2geometry/src/s2/s2contains_vertex_query.cc +39 -0
- package/third_party/s2geometry/src/s2/s2contains_vertex_query.h +66 -0
- package/third_party/s2geometry/src/s2/s2contains_vertex_query_test.cc +67 -0
- package/third_party/s2geometry/src/s2/s2convex_hull_query.cc +198 -0
- package/third_party/s2geometry/src/s2/s2convex_hull_query.h +110 -0
- package/third_party/s2geometry/src/s2/s2convex_hull_query_test.cc +208 -0
- package/third_party/s2geometry/src/s2/s2coords.cc +146 -0
- package/third_party/s2geometry/src/s2/s2coords.h +459 -0
- package/third_party/s2geometry/src/s2/s2coords_internal.h +71 -0
- package/third_party/s2geometry/src/s2/s2coords_test.cc +218 -0
- package/third_party/s2geometry/src/s2/s2crossing_edge_query.cc +380 -0
- package/third_party/s2geometry/src/s2/s2crossing_edge_query.h +220 -0
- package/third_party/s2geometry/src/s2/s2crossing_edge_query_test.cc +382 -0
- package/third_party/s2geometry/src/s2/s2debug.cc +23 -0
- package/third_party/s2geometry/src/s2/s2debug.h +69 -0
- package/third_party/s2geometry/src/s2/s2distance_target.h +165 -0
- package/third_party/s2geometry/src/s2/s2earth.cc +52 -0
- package/third_party/s2geometry/src/s2/s2earth.h +268 -0
- package/third_party/s2geometry/src/s2/s2earth_test.cc +146 -0
- package/third_party/s2geometry/src/s2/s2edge_clipping.cc +462 -0
- package/third_party/s2geometry/src/s2/s2edge_clipping.h +183 -0
- package/third_party/s2geometry/src/s2/s2edge_clipping_test.cc +335 -0
- package/third_party/s2geometry/src/s2/s2edge_crosser.cc +85 -0
- package/third_party/s2geometry/src/s2/s2edge_crosser.h +343 -0
- package/third_party/s2geometry/src/s2/s2edge_crosser_test.cc +264 -0
- package/third_party/s2geometry/src/s2/s2edge_crossings.cc +515 -0
- package/third_party/s2geometry/src/s2/s2edge_crossings.h +138 -0
- package/third_party/s2geometry/src/s2/s2edge_crossings_internal.h +59 -0
- package/third_party/s2geometry/src/s2/s2edge_crossings_test.cc +246 -0
- package/third_party/s2geometry/src/s2/s2edge_distances.cc +419 -0
- package/third_party/s2geometry/src/s2/s2edge_distances.h +192 -0
- package/third_party/s2geometry/src/s2/s2edge_distances_test.cc +539 -0
- package/third_party/s2geometry/src/s2/s2edge_tessellator.cc +276 -0
- package/third_party/s2geometry/src/s2/s2edge_tessellator.h +101 -0
- package/third_party/s2geometry/src/s2/s2edge_tessellator_test.cc +492 -0
- package/third_party/s2geometry/src/s2/s2edge_vector_shape.h +85 -0
- package/third_party/s2geometry/src/s2/s2edge_vector_shape_test.cc +66 -0
- package/third_party/s2geometry/src/s2/s2error.cc +29 -0
- package/third_party/s2geometry/src/s2/s2error.h +147 -0
- package/third_party/s2geometry/src/s2/s2error_test.cc +31 -0
- package/third_party/s2geometry/src/s2/s2furthest_edge_query.cc +117 -0
- package/third_party/s2geometry/src/s2/s2furthest_edge_query.h +439 -0
- package/third_party/s2geometry/src/s2/s2furthest_edge_query_test.cc +487 -0
- package/third_party/s2geometry/src/s2/s2latlng.cc +90 -0
- package/third_party/s2geometry/src/s2/s2latlng.h +234 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect.cc +727 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect.h +434 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect_bounder.cc +344 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect_bounder.h +89 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect_bounder_test.cc +306 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect_test.cc +1030 -0
- package/third_party/s2geometry/src/s2/s2latlng_test.cc +165 -0
- package/third_party/s2geometry/src/s2/s2lax_loop_shape.cc +104 -0
- package/third_party/s2geometry/src/s2/s2lax_loop_shape.h +153 -0
- package/third_party/s2geometry/src/s2/s2lax_loop_shape_test.cc +101 -0
- package/third_party/s2geometry/src/s2/s2lax_polygon_shape.cc +348 -0
- package/third_party/s2geometry/src/s2/s2lax_polygon_shape.h +183 -0
- package/third_party/s2geometry/src/s2/s2lax_polygon_shape_test.cc +234 -0
- package/third_party/s2geometry/src/s2/s2lax_polyline_shape.cc +118 -0
- package/third_party/s2geometry/src/s2/s2lax_polyline_shape.h +124 -0
- package/third_party/s2geometry/src/s2/s2lax_polyline_shape_test.cc +62 -0
- package/third_party/s2geometry/src/s2/s2loop.cc +1509 -0
- package/third_party/s2geometry/src/s2/s2loop.h +711 -0
- package/third_party/s2geometry/src/s2/s2loop_measures.cc +313 -0
- package/third_party/s2geometry/src/s2/s2loop_measures.h +280 -0
- package/third_party/s2geometry/src/s2/s2loop_measures_test.cc +367 -0
- package/third_party/s2geometry/src/s2/s2loop_test.cc +1371 -0
- package/third_party/s2geometry/src/s2/s2max_distance_targets.cc +265 -0
- package/third_party/s2geometry/src/s2/s2max_distance_targets.h +241 -0
- package/third_party/s2geometry/src/s2/s2max_distance_targets_test.cc +367 -0
- package/third_party/s2geometry/src/s2/s2measures.cc +128 -0
- package/third_party/s2geometry/src/s2/s2measures.h +78 -0
- package/third_party/s2geometry/src/s2/s2measures_test.cc +135 -0
- package/third_party/s2geometry/src/s2/s2metrics.cc +122 -0
- package/third_party/s2geometry/src/s2/s2metrics.h +199 -0
- package/third_party/s2geometry/src/s2/s2metrics_test.cc +127 -0
- package/third_party/s2geometry/src/s2/s2min_distance_targets.cc +295 -0
- package/third_party/s2geometry/src/s2/s2min_distance_targets.h +273 -0
- package/third_party/s2geometry/src/s2/s2min_distance_targets_test.cc +239 -0
- package/third_party/s2geometry/src/s2/s2padded_cell.cc +162 -0
- package/third_party/s2geometry/src/s2/s2padded_cell.h +108 -0
- package/third_party/s2geometry/src/s2/s2padded_cell_test.cc +138 -0
- package/third_party/s2geometry/src/s2/s2point.h +38 -0
- package/third_party/s2geometry/src/s2/s2point_compression.cc +388 -0
- package/third_party/s2geometry/src/s2/s2point_compression.h +78 -0
- package/third_party/s2geometry/src/s2/s2point_compression_test.cc +305 -0
- package/third_party/s2geometry/src/s2/s2point_index.h +345 -0
- package/third_party/s2geometry/src/s2/s2point_index_test.cc +147 -0
- package/third_party/s2geometry/src/s2/s2point_region.cc +72 -0
- package/third_party/s2geometry/src/s2/s2point_region.h +76 -0
- package/third_party/s2geometry/src/s2/s2point_region_test.cc +100 -0
- package/third_party/s2geometry/src/s2/s2point_span.h +57 -0
- package/third_party/s2geometry/src/s2/s2point_test.cc +47 -0
- package/third_party/s2geometry/src/s2/s2point_vector_shape.h +127 -0
- package/third_party/s2geometry/src/s2/s2point_vector_shape_test.cc +59 -0
- package/third_party/s2geometry/src/s2/s2pointutil.cc +131 -0
- package/third_party/s2geometry/src/s2/s2pointutil.h +138 -0
- package/third_party/s2geometry/src/s2/s2pointutil_test.cc +157 -0
- package/third_party/s2geometry/src/s2/s2polygon.cc +1569 -0
- package/third_party/s2geometry/src/s2/s2polygon.h +934 -0
- package/third_party/s2geometry/src/s2/s2polygon_test.cc +3025 -0
- package/third_party/s2geometry/src/s2/s2polyline.cc +645 -0
- package/third_party/s2geometry/src/s2/s2polyline.h +379 -0
- package/third_party/s2geometry/src/s2/s2polyline_alignment.cc +414 -0
- package/third_party/s2geometry/src/s2/s2polyline_alignment.h +245 -0
- package/third_party/s2geometry/src/s2/s2polyline_alignment_internal.h +158 -0
- package/third_party/s2geometry/src/s2/s2polyline_alignment_test.cc +610 -0
- package/third_party/s2geometry/src/s2/s2polyline_measures.cc +42 -0
- package/third_party/s2geometry/src/s2/s2polyline_measures.h +53 -0
- package/third_party/s2geometry/src/s2/s2polyline_measures_test.cc +57 -0
- package/third_party/s2geometry/src/s2/s2polyline_simplifier.cc +187 -0
- package/third_party/s2geometry/src/s2/s2polyline_simplifier.h +109 -0
- package/third_party/s2geometry/src/s2/s2polyline_simplifier_test.cc +165 -0
- package/third_party/s2geometry/src/s2/s2polyline_test.cc +554 -0
- package/third_party/s2geometry/src/s2/s2predicates.cc +1486 -0
- package/third_party/s2geometry/src/s2/s2predicates.h +282 -0
- package/third_party/s2geometry/src/s2/s2predicates_internal.h +135 -0
- package/third_party/s2geometry/src/s2/s2predicates_test.cc +1427 -0
- package/third_party/s2geometry/src/s2/s2projections.cc +109 -0
- package/third_party/s2geometry/src/s2/s2projections.h +161 -0
- package/third_party/s2geometry/src/s2/s2projections_test.cc +78 -0
- package/third_party/s2geometry/src/s2/s2r2rect.cc +88 -0
- package/third_party/s2geometry/src/s2/s2r2rect.h +292 -0
- package/third_party/s2geometry/src/s2/s2r2rect_test.cc +312 -0
- package/third_party/s2geometry/src/s2/s2region.cc +26 -0
- package/third_party/s2geometry/src/s2/s2region.h +142 -0
- package/third_party/s2geometry/src/s2/s2region_coverer.cc +514 -0
- package/third_party/s2geometry/src/s2/s2region_coverer.h +356 -0
- package/third_party/s2geometry/src/s2/s2region_coverer_test.cc +509 -0
- package/third_party/s2geometry/src/s2/s2region_intersection.cc +84 -0
- package/third_party/s2geometry/src/s2/s2region_intersection.h +79 -0
- package/third_party/s2geometry/src/s2/s2region_term_indexer.cc +270 -0
- package/third_party/s2geometry/src/s2/s2region_term_indexer.h +299 -0
- package/third_party/s2geometry/src/s2/s2region_term_indexer_test.cc +209 -0
- package/third_party/s2geometry/src/s2/s2region_test.cc +370 -0
- package/third_party/s2geometry/src/s2/s2region_union.cc +90 -0
- package/third_party/s2geometry/src/s2/s2region_union.h +83 -0
- package/third_party/s2geometry/src/s2/s2region_union_test.cc +89 -0
- package/third_party/s2geometry/src/s2/s2shape.h +283 -0
- package/third_party/s2geometry/src/s2/s2shape_index.cc +321 -0
- package/third_party/s2geometry/src/s2/s2shape_index.h +781 -0
- package/third_party/s2geometry/src/s2/s2shape_index_buffered_region.cc +113 -0
- package/third_party/s2geometry/src/s2/s2shape_index_buffered_region.h +135 -0
- package/third_party/s2geometry/src/s2/s2shape_index_buffered_region_test.cc +162 -0
- package/third_party/s2geometry/src/s2/s2shape_index_measures.cc +92 -0
- package/third_party/s2geometry/src/s2/s2shape_index_measures.h +100 -0
- package/third_party/s2geometry/src/s2/s2shape_index_measures_test.cc +136 -0
- package/third_party/s2geometry/src/s2/s2shape_index_region.h +350 -0
- package/third_party/s2geometry/src/s2/s2shape_index_region_test.cc +161 -0
- package/third_party/s2geometry/src/s2/s2shape_index_test.cc +24 -0
- package/third_party/s2geometry/src/s2/s2shape_measures.cc +138 -0
- package/third_party/s2geometry/src/s2/s2shape_measures.h +95 -0
- package/third_party/s2geometry/src/s2/s2shape_measures_test.cc +139 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_build_polygon_boundaries.cc +120 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_build_polygon_boundaries.h +66 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_build_polygon_boundaries_test.cc +170 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_coding.cc +253 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_coding.h +283 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_coding_test.cc +54 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_contains_brute_force.cc +40 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_contains_brute_force.h +41 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_contains_brute_force_test.cc +55 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_count_edges.h +57 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_count_edges_test.cc +43 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_edge_iterator.cc +45 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_edge_iterator.h +72 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_edge_iterator_test.cc +116 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_get_reference_point.cc +107 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_get_reference_point.h +48 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_get_reference_point_test.cc +104 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_range_iterator.cc +58 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_range_iterator.h +65 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_range_iterator_test.cc +61 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_shape_edge.h +58 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_shape_edge_id.h +97 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_testing.cc +104 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_testing.h +36 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_visit_crossing_edge_pairs.cc +440 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_visit_crossing_edge_pairs.h +72 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_visit_crossing_edge_pairs_test.cc +184 -0
- package/third_party/s2geometry/src/s2/s2testing.cc +464 -0
- package/third_party/s2geometry/src/s2/s2testing.h +385 -0
- package/third_party/s2geometry/src/s2/s2testing_test.cc +166 -0
- package/third_party/s2geometry/src/s2/s2text_format.cc +506 -0
- package/third_party/s2geometry/src/s2/s2text_format.h +289 -0
- package/third_party/s2geometry/src/s2/s2text_format_test.cc +417 -0
- package/third_party/s2geometry/src/s2/s2wedge_relations.cc +80 -0
- package/third_party/s2geometry/src/s2/s2wedge_relations.h +64 -0
- package/third_party/s2geometry/src/s2/s2wedge_relations_test.cc +89 -0
- package/third_party/s2geometry/src/s2/sequence_lexicon.h +296 -0
- package/third_party/s2geometry/src/s2/sequence_lexicon_test.cc +113 -0
- package/third_party/s2geometry/src/s2/strings/ostringstream.cc +35 -0
- package/third_party/s2geometry/src/s2/strings/ostringstream.h +105 -0
- package/third_party/s2geometry/src/s2/strings/serialize.cc +46 -0
- package/third_party/s2geometry/src/s2/strings/serialize.h +40 -0
- package/third_party/s2geometry/src/s2/third_party/absl/algorithm/algorithm.h +187 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/attributes.h +666 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/casts.h +189 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/config.h +462 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/dynamic_annotations.cc +129 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/dynamic_annotations.h +394 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/atomic_hook.h +168 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/identity.h +33 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/inline_variable.h +117 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/invoke.h +188 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/raw_logging.cc +254 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/raw_logging.h +205 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/throw_delegate.cc +106 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/throw_delegate.h +71 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/unaligned_access.h +322 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/log_severity.h +77 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/macros.h +236 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/optimization.h +177 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/policy_checks.h +124 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/port.h +97 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/thread_annotations.h +277 -0
- package/third_party/s2geometry/src/s2/third_party/absl/container/fixed_array.h +523 -0
- package/third_party/s2geometry/src/s2/third_party/absl/container/inlined_vector.h +1453 -0
- package/third_party/s2geometry/src/s2/third_party/absl/container/internal/compressed_tuple.h +191 -0
- package/third_party/s2geometry/src/s2/third_party/absl/container/internal/container_memory.h +424 -0
- package/third_party/s2geometry/src/s2/third_party/absl/container/internal/layout.h +739 -0
- package/third_party/s2geometry/src/s2/third_party/absl/memory/memory.h +755 -0
- package/third_party/s2geometry/src/s2/third_party/absl/meta/type_traits.h +436 -0
- package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128.cc +232 -0
- package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128.h +656 -0
- package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128_have_intrinsic.inc +3 -0
- package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128_no_intrinsic.inc +3 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/ascii.cc +198 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/ascii.h +239 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/ascii_ctype.h +66 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/bits.h +53 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/memutil.cc +110 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/memutil.h +146 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/resize_uninitialized.h +72 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/match.cc +38 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/match.h +89 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/numbers.cc +909 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/numbers.h +187 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/str_cat.cc +240 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/str_cat.h +398 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/str_join.h +22 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/str_split.cc +47 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/str_split.h +43 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/string_view.cc +245 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/string_view.h +602 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/strip.cc +42 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/strip.h +130 -0
- package/third_party/s2geometry/src/s2/third_party/absl/types/span.h +793 -0
- package/third_party/s2geometry/src/s2/third_party/absl/utility/utility.h +299 -0
- package/third_party/s2geometry/src/s2/util/bits/bit-interleave.cc +274 -0
- package/third_party/s2geometry/src/s2/util/bits/bit-interleave.h +53 -0
- package/third_party/s2geometry/src/s2/util/bits/bits.cc +155 -0
- package/third_party/s2geometry/src/s2/util/bits/bits.h +745 -0
- package/third_party/s2geometry/src/s2/util/coding/coder.cc +83 -0
- package/third_party/s2geometry/src/s2/util/coding/coder.h +553 -0
- package/third_party/s2geometry/src/s2/util/coding/nth-derivative.h +134 -0
- package/third_party/s2geometry/src/s2/util/coding/transforms.h +62 -0
- package/third_party/s2geometry/src/s2/util/coding/varint.cc +289 -0
- package/third_party/s2geometry/src/s2/util/coding/varint.h +476 -0
- package/third_party/s2geometry/src/s2/util/endian/endian.h +859 -0
- package/third_party/s2geometry/src/s2/util/gtl/btree.h +2471 -0
- package/third_party/s2geometry/src/s2/util/gtl/btree_container.h +411 -0
- package/third_party/s2geometry/src/s2/util/gtl/btree_map.h +79 -0
- package/third_party/s2geometry/src/s2/util/gtl/btree_set.h +73 -0
- package/third_party/s2geometry/src/s2/util/gtl/compact_array.h +653 -0
- package/third_party/s2geometry/src/s2/util/gtl/container_logging.h +291 -0
- package/third_party/s2geometry/src/s2/util/gtl/dense_hash_set.h +358 -0
- package/third_party/s2geometry/src/s2/util/gtl/densehashtable.h +1493 -0
- package/third_party/s2geometry/src/s2/util/gtl/hashtable_common.h +253 -0
- package/third_party/s2geometry/src/s2/util/gtl/layout.h +28 -0
- package/third_party/s2geometry/src/s2/util/gtl/legacy_random_shuffle.h +77 -0
- package/third_party/s2geometry/src/s2/util/hash/mix.h +76 -0
- package/third_party/s2geometry/src/s2/util/math/exactfloat/exactfloat.cc +832 -0
- package/third_party/s2geometry/src/s2/util/math/exactfloat/exactfloat.h +646 -0
- package/third_party/s2geometry/src/s2/util/math/mathutil.cc +75 -0
- package/third_party/s2geometry/src/s2/util/math/mathutil.h +189 -0
- package/third_party/s2geometry/src/s2/util/math/matrix3x3.h +574 -0
- package/third_party/s2geometry/src/s2/util/math/vector.h +569 -0
- package/third_party/s2geometry/src/s2/util/math/vector3_hash.h +54 -0
- package/third_party/s2geometry/src/s2/util/units/length-units.cc +21 -0
- package/third_party/s2geometry/src/s2/util/units/length-units.h +135 -0
- package/third_party/s2geometry/src/s2/util/units/physical-units.h +313 -0
- package/third_party/s2geometry/src/s2/value_lexicon.h +234 -0
- package/third_party/s2geometry/src/s2/value_lexicon_test.cc +121 -0
- package/third_party/s2geometry/third_party/cmake/FindGFlags.cmake +48 -0
- package/third_party/s2geometry/third_party/cmake/FindGlog.cmake +48 -0
|
@@ -0,0 +1,832 @@
|
|
|
1
|
+
// Copyright 2009 Google Inc. All Rights Reserved.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS-IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
//
|
|
15
|
+
|
|
16
|
+
// Author: ericv@google.com (Eric Veach)
|
|
17
|
+
|
|
18
|
+
#include "s2/util/math/exactfloat/exactfloat.h"
|
|
19
|
+
|
|
20
|
+
#include <cstdio>
|
|
21
|
+
#include <cstdlib>
|
|
22
|
+
#include <cstring>
|
|
23
|
+
#include <algorithm>
|
|
24
|
+
#include <cmath>
|
|
25
|
+
#include <limits>
|
|
26
|
+
|
|
27
|
+
#include <openssl/bn.h>
|
|
28
|
+
#include <openssl/crypto.h> // for OPENSSL_free
|
|
29
|
+
|
|
30
|
+
#include "s2/base/integral_types.h"
|
|
31
|
+
#include "s2/base/logging.h"
|
|
32
|
+
#include "s2/third_party/absl/base/macros.h"
|
|
33
|
+
#include "s2/third_party/absl/container/fixed_array.h"
|
|
34
|
+
|
|
35
|
+
using std::max;
|
|
36
|
+
using std::min;
|
|
37
|
+
|
|
38
|
+
// Define storage for constants.
|
|
39
|
+
const int ExactFloat::kMinExp;
|
|
40
|
+
const int ExactFloat::kMaxExp;
|
|
41
|
+
const int ExactFloat::kMaxPrec;
|
|
42
|
+
const int32 ExactFloat::kExpNaN;
|
|
43
|
+
const int32 ExactFloat::kExpInfinity;
|
|
44
|
+
const int32 ExactFloat::kExpZero;
|
|
45
|
+
const int ExactFloat::kDoubleMantissaBits;
|
|
46
|
+
|
|
47
|
+
// To simplify the overflow/underflow logic, we limit the exponent and
|
|
48
|
+
// precision range so that (2 * bn_exp_) does not overflow an "int". We take
|
|
49
|
+
// advantage of this, for example, by only checking for overflow/underflow
|
|
50
|
+
// *after* multiplying two numbers.
|
|
51
|
+
static_assert(
|
|
52
|
+
ExactFloat::kMaxExp <= INT_MAX / 2 &&
|
|
53
|
+
ExactFloat::kMinExp - ExactFloat::kMaxPrec >= INT_MIN / 2,
|
|
54
|
+
"exactfloat exponent might overflow");
|
|
55
|
+
|
|
56
|
+
// We define a few simple extensions to the OpenSSL's BIGNUM interface.
|
|
57
|
+
// In some cases these depend on BIGNUM internal fields, so they might
|
|
58
|
+
// require tweaking if the BIGNUM implementation changes significantly.
|
|
59
|
+
// These are just thin wrappers for BoringSSL.
|
|
60
|
+
|
|
61
|
+
#ifdef OPENSSL_IS_BORINGSSL
|
|
62
|
+
|
|
63
|
+
inline static void BN_ext_set_uint64(BIGNUM* bn, uint64 v) {
|
|
64
|
+
S2_CHECK(BN_set_u64(bn, v));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Return the absolute value of a BIGNUM as a 64-bit unsigned integer.
|
|
68
|
+
// Requires that BIGNUM fits into 64 bits.
|
|
69
|
+
inline static uint64 BN_ext_get_uint64(const BIGNUM* bn) {
|
|
70
|
+
uint64_t u64;
|
|
71
|
+
if (!BN_get_u64(bn, &u64)) {
|
|
72
|
+
S2_DCHECK(false) << "BN has " << BN_num_bits(bn) << " bits";
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
return u64;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static int BN_ext_count_low_zero_bits(const BIGNUM* bn) {
|
|
79
|
+
return BN_count_low_zero_bits(bn);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#else // !defined(OPENSSL_IS_BORINGSSL)
|
|
83
|
+
|
|
84
|
+
// Set a BIGNUM to the given unsigned 64-bit value.
|
|
85
|
+
inline static void BN_ext_set_uint64(BIGNUM* bn, uint64 v) {
|
|
86
|
+
#if BN_BITS2 == 64
|
|
87
|
+
S2_CHECK(BN_set_word(bn, v));
|
|
88
|
+
#else
|
|
89
|
+
static_assert(BN_BITS2 == 32, "at least 32 bit openssl build needed");
|
|
90
|
+
S2_CHECK(BN_set_word(bn, static_cast<uint32>(v >> 32)));
|
|
91
|
+
S2_CHECK(BN_lshift(bn, bn, 32));
|
|
92
|
+
S2_CHECK(BN_add_word(bn, static_cast<uint32>(v)));
|
|
93
|
+
#endif
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Return the absolute value of a BIGNUM as a 64-bit unsigned integer.
|
|
97
|
+
// Requires that BIGNUM fits into 64 bits.
|
|
98
|
+
inline static uint64 BN_ext_get_uint64(const BIGNUM* bn) {
|
|
99
|
+
S2_DCHECK_LE(BN_num_bytes(bn), sizeof(uint64));
|
|
100
|
+
#if BN_BITS2 == 64
|
|
101
|
+
return BN_get_word(bn);
|
|
102
|
+
#else
|
|
103
|
+
static_assert(BN_BITS2 == 32, "at least 32 bit openssl build needed");
|
|
104
|
+
if (bn->top == 0) return 0;
|
|
105
|
+
if (bn->top == 1) return BN_get_word(bn);
|
|
106
|
+
S2_DCHECK_EQ(bn->top, 2);
|
|
107
|
+
return (static_cast<uint64>(bn->d[1]) << 32) + bn->d[0];
|
|
108
|
+
#endif
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
112
|
+
|
|
113
|
+
// Count the number of low-order zero bits in the given BIGNUM (ignoring its
|
|
114
|
+
// sign). Returns 0 if the argument is zero.
|
|
115
|
+
static int BN_ext_count_low_zero_bits(const BIGNUM* bn) {
|
|
116
|
+
int count = 0;
|
|
117
|
+
for (int i = 0; i < bn->top; ++i) {
|
|
118
|
+
BN_ULONG w = bn->d[i];
|
|
119
|
+
if (w == 0) {
|
|
120
|
+
count += 8 * sizeof(BN_ULONG);
|
|
121
|
+
} else {
|
|
122
|
+
for (; (w & 1) == 0; w >>= 1) {
|
|
123
|
+
++count;
|
|
124
|
+
}
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return count;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
#else // OPENSSL_VERSION_NUMBER >= 0x10100000L
|
|
132
|
+
|
|
133
|
+
static int BN_ext_count_low_zero_bits(const BIGNUM* bn) {
|
|
134
|
+
// In OpenSSL >= 1.1, BIGNUM is an opaque type, so d and top
|
|
135
|
+
// cannot be accessed. The bytes must be copied out at a ~25%
|
|
136
|
+
// performance penalty.
|
|
137
|
+
absl::FixedArray<unsigned char> bytes(BN_num_bytes(bn));
|
|
138
|
+
// "le" indicates little endian.
|
|
139
|
+
S2_CHECK_EQ(BN_bn2lebinpad(bn, bytes.data(), bytes.size()), bytes.size());
|
|
140
|
+
|
|
141
|
+
int count = 0;
|
|
142
|
+
for (unsigned char c : bytes) {
|
|
143
|
+
if (c == 0) {
|
|
144
|
+
count += 8;
|
|
145
|
+
} else {
|
|
146
|
+
for (; (c & 1) == 0; c >>= 1) {
|
|
147
|
+
++count;
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return count;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
#endif // OPENSSL_VERSION_NUMBER >= 0x10100000L
|
|
156
|
+
|
|
157
|
+
#endif // !defined(OPENSSL_IS_BORINGSSL)
|
|
158
|
+
|
|
159
|
+
ExactFloat::ExactFloat(double v) {
|
|
160
|
+
sign_ = std::signbit(v) ? -1 : 1;
|
|
161
|
+
if (std::isnan(v)) {
|
|
162
|
+
set_nan();
|
|
163
|
+
} else if (std::isinf(v)) {
|
|
164
|
+
set_inf(sign_);
|
|
165
|
+
} else {
|
|
166
|
+
// The following code is much simpler than messing about with bit masks,
|
|
167
|
+
// has the advantage of handling denormalized numbers and zero correctly,
|
|
168
|
+
// and is actually quite efficient (at least compared to the rest of this
|
|
169
|
+
// code). "f" is a fraction in the range [0.5, 1), so if we shift it left
|
|
170
|
+
// by the number of mantissa bits in a double (53, including the leading
|
|
171
|
+
// "1") then the result is always an integer.
|
|
172
|
+
int exp;
|
|
173
|
+
double f = frexp(fabs(v), &exp);
|
|
174
|
+
uint64 m = static_cast<uint64>(ldexp(f, kDoubleMantissaBits));
|
|
175
|
+
BN_ext_set_uint64(bn_.get(), m);
|
|
176
|
+
bn_exp_ = exp - kDoubleMantissaBits;
|
|
177
|
+
Canonicalize();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
ExactFloat::ExactFloat(int v) {
|
|
182
|
+
sign_ = (v >= 0) ? 1 : -1;
|
|
183
|
+
// Note that this works even for INT_MIN because the parameter type for
|
|
184
|
+
// BN_set_word() is unsigned.
|
|
185
|
+
S2_CHECK(BN_set_word(bn_.get(), abs(v)));
|
|
186
|
+
bn_exp_ = 0;
|
|
187
|
+
Canonicalize();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
ExactFloat::ExactFloat(const ExactFloat& b)
|
|
191
|
+
: sign_(b.sign_),
|
|
192
|
+
bn_exp_(b.bn_exp_) {
|
|
193
|
+
BN_copy(bn_.get(), b.bn_.get());
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
ExactFloat ExactFloat::SignedZero(int sign) {
|
|
197
|
+
ExactFloat r;
|
|
198
|
+
r.set_zero(sign);
|
|
199
|
+
return r;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
ExactFloat ExactFloat::Infinity(int sign) {
|
|
203
|
+
ExactFloat r;
|
|
204
|
+
r.set_inf(sign);
|
|
205
|
+
return r;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
ExactFloat ExactFloat::NaN() {
|
|
209
|
+
ExactFloat r;
|
|
210
|
+
r.set_nan();
|
|
211
|
+
return r;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
int ExactFloat::prec() const {
|
|
215
|
+
return BN_num_bits(bn_.get());
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
int ExactFloat::exp() const {
|
|
219
|
+
S2_DCHECK(is_normal());
|
|
220
|
+
return bn_exp_ + BN_num_bits(bn_.get());
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
void ExactFloat::set_zero(int sign) {
|
|
224
|
+
sign_ = sign;
|
|
225
|
+
bn_exp_ = kExpZero;
|
|
226
|
+
if (!BN_is_zero(bn_.get())) BN_zero(bn_.get());
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
void ExactFloat::set_inf(int sign) {
|
|
230
|
+
sign_ = sign;
|
|
231
|
+
bn_exp_ = kExpInfinity;
|
|
232
|
+
if (!BN_is_zero(bn_.get())) BN_zero(bn_.get());
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
void ExactFloat::set_nan() {
|
|
236
|
+
sign_ = 1;
|
|
237
|
+
bn_exp_ = kExpNaN;
|
|
238
|
+
if (!BN_is_zero(bn_.get())) BN_zero(bn_.get());
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
double ExactFloat::ToDouble() const {
|
|
242
|
+
// If the mantissa has too many bits, we need to round it.
|
|
243
|
+
if (prec() <= kDoubleMantissaBits) {
|
|
244
|
+
return ToDoubleHelper();
|
|
245
|
+
} else {
|
|
246
|
+
ExactFloat r = RoundToMaxPrec(kDoubleMantissaBits, kRoundTiesToEven);
|
|
247
|
+
return r.ToDoubleHelper();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
double ExactFloat::ToDoubleHelper() const {
|
|
252
|
+
S2_DCHECK_LE(BN_num_bits(bn_.get()), kDoubleMantissaBits);
|
|
253
|
+
if (!is_normal()) {
|
|
254
|
+
if (is_zero()) return copysign(0, sign_);
|
|
255
|
+
if (is_inf()) {
|
|
256
|
+
return std::copysign(std::numeric_limits<double>::infinity(), sign_);
|
|
257
|
+
}
|
|
258
|
+
return std::copysign(std::numeric_limits<double>::quiet_NaN(), sign_);
|
|
259
|
+
}
|
|
260
|
+
uint64 d_mantissa = BN_ext_get_uint64(bn_.get());
|
|
261
|
+
// We rely on ldexp() to handle overflow and underflow. (It will return a
|
|
262
|
+
// signed zero or infinity if the result is too small or too large.)
|
|
263
|
+
return sign_ * ldexp(static_cast<double>(d_mantissa), bn_exp_);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
ExactFloat ExactFloat::RoundToMaxPrec(int max_prec, RoundingMode mode) const {
|
|
267
|
+
// The "kRoundTiesToEven" mode requires at least 2 bits of precision
|
|
268
|
+
// (otherwise both adjacent representable values may be odd).
|
|
269
|
+
S2_DCHECK_GE(max_prec, 2);
|
|
270
|
+
S2_DCHECK_LE(max_prec, kMaxPrec);
|
|
271
|
+
|
|
272
|
+
// The following test also catches zero, infinity, and NaN.
|
|
273
|
+
int shift = prec() - max_prec;
|
|
274
|
+
if (shift <= 0) return *this;
|
|
275
|
+
|
|
276
|
+
// Round by removing the appropriate number of bits from the mantissa. Note
|
|
277
|
+
// that if the value is rounded up to a power of 2, the high-order bit
|
|
278
|
+
// position may increase, but in that case Canonicalize() will remove at
|
|
279
|
+
// least one zero bit and so the output will still have prec() <= max_prec.
|
|
280
|
+
return RoundToPowerOf2(bn_exp_ + shift, mode);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
ExactFloat ExactFloat::RoundToPowerOf2(int bit_exp, RoundingMode mode) const {
|
|
284
|
+
S2_DCHECK_GE(bit_exp, kMinExp - kMaxPrec);
|
|
285
|
+
S2_DCHECK_LE(bit_exp, kMaxExp);
|
|
286
|
+
|
|
287
|
+
// If the exponent is already large enough, or the value is zero, infinity,
|
|
288
|
+
// or NaN, then there is nothing to do.
|
|
289
|
+
int shift = bit_exp - bn_exp_;
|
|
290
|
+
if (shift <= 0) return *this;
|
|
291
|
+
S2_DCHECK(is_normal());
|
|
292
|
+
|
|
293
|
+
// Convert rounding up/down to toward/away from zero, so that we don't need
|
|
294
|
+
// to consider the sign of the number from this point onward.
|
|
295
|
+
if (mode == kRoundTowardPositive) {
|
|
296
|
+
mode = (sign_ > 0) ? kRoundAwayFromZero : kRoundTowardZero;
|
|
297
|
+
} else if (mode == kRoundTowardNegative) {
|
|
298
|
+
mode = (sign_ > 0) ? kRoundTowardZero : kRoundAwayFromZero;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Rounding consists of right-shifting the mantissa by "shift", and then
|
|
302
|
+
// possibly incrementing the result (depending on the rounding mode, the
|
|
303
|
+
// bits that were discarded, and sometimes the lowest kept bit). The
|
|
304
|
+
// following code figures out whether we need to increment.
|
|
305
|
+
ExactFloat r;
|
|
306
|
+
bool increment = false;
|
|
307
|
+
if (mode == kRoundTowardZero) {
|
|
308
|
+
// Never increment.
|
|
309
|
+
} else if (mode == kRoundTiesAwayFromZero) {
|
|
310
|
+
// Increment if the highest discarded bit is 1.
|
|
311
|
+
if (BN_is_bit_set(bn_.get(), shift - 1))
|
|
312
|
+
increment = true;
|
|
313
|
+
} else if (mode == kRoundAwayFromZero) {
|
|
314
|
+
// Increment unless all discarded bits are zero.
|
|
315
|
+
if (BN_ext_count_low_zero_bits(bn_.get()) < shift)
|
|
316
|
+
increment = true;
|
|
317
|
+
} else {
|
|
318
|
+
S2_DCHECK_EQ(mode, kRoundTiesToEven);
|
|
319
|
+
// Let "w/xyz" denote a mantissa where "w" is the lowest kept bit and
|
|
320
|
+
// "xyz" are the discarded bits. Then using regexp notation:
|
|
321
|
+
// ./0.* -> Don't increment (fraction < 1/2)
|
|
322
|
+
// 0/10* -> Don't increment (fraction = 1/2, kept part even)
|
|
323
|
+
// 1/10* -> Increment (fraction = 1/2, kept part odd)
|
|
324
|
+
// ./1.*1.* -> Increment (fraction > 1/2)
|
|
325
|
+
if (BN_is_bit_set(bn_.get(), shift - 1) &&
|
|
326
|
+
((BN_is_bit_set(bn_.get(), shift) ||
|
|
327
|
+
BN_ext_count_low_zero_bits(bn_.get()) < shift - 1))) {
|
|
328
|
+
increment = true;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
r.bn_exp_ = bn_exp_ + shift;
|
|
332
|
+
S2_CHECK(BN_rshift(r.bn_.get(), bn_.get(), shift));
|
|
333
|
+
if (increment) {
|
|
334
|
+
S2_CHECK(BN_add_word(r.bn_.get(), 1));
|
|
335
|
+
}
|
|
336
|
+
r.sign_ = sign_;
|
|
337
|
+
r.Canonicalize();
|
|
338
|
+
return r;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
int ExactFloat::NumSignificantDigitsForPrec(int prec) {
|
|
342
|
+
// The simplest bound is
|
|
343
|
+
//
|
|
344
|
+
// d <= 1 + ceil(prec * log10(2))
|
|
345
|
+
//
|
|
346
|
+
// The following bound is tighter by 0.5 digits on average, but requires
|
|
347
|
+
// the exponent to be known as well:
|
|
348
|
+
//
|
|
349
|
+
// d <= ceil(exp * log10(2)) - floor((exp - prec) * log10(2))
|
|
350
|
+
//
|
|
351
|
+
// Since either of these bounds can be too large by 0, 1, or 2 digits, we
|
|
352
|
+
// stick with the simpler first bound.
|
|
353
|
+
return static_cast<int>(1 + ceil(prec * (M_LN2 / M_LN10)));
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Numbers are always formatted with at least this many significant digits.
|
|
357
|
+
// This prevents small integers from being formatted in exponential notation
|
|
358
|
+
// (e.g. 1024 formatted as 1e+03), and also avoids the confusion of having
|
|
359
|
+
// supposedly "high precision" numbers formatted with just 1 or 2 digits
|
|
360
|
+
// (e.g. 1/512 == 0.001953125 formatted as 0.002).
|
|
361
|
+
static const int kMinSignificantDigits = 10;
|
|
362
|
+
|
|
363
|
+
string ExactFloat::ToString() const {
|
|
364
|
+
int max_digits = max(kMinSignificantDigits,
|
|
365
|
+
NumSignificantDigitsForPrec(prec()));
|
|
366
|
+
return ToStringWithMaxDigits(max_digits);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
string ExactFloat::ToStringWithMaxDigits(int max_digits) const {
|
|
370
|
+
S2_DCHECK_GT(max_digits, 0);
|
|
371
|
+
if (!is_normal()) {
|
|
372
|
+
if (is_nan()) return "nan";
|
|
373
|
+
if (is_zero()) return (sign_ < 0) ? "-0" : "0";
|
|
374
|
+
return (sign_ < 0) ? "-inf" : "inf";
|
|
375
|
+
}
|
|
376
|
+
string digits;
|
|
377
|
+
int exp10 = GetDecimalDigits(max_digits, &digits);
|
|
378
|
+
string str;
|
|
379
|
+
if (sign_ < 0) str.push_back('-');
|
|
380
|
+
|
|
381
|
+
// We use the standard '%g' formatting rules. If the exponent is less than
|
|
382
|
+
// -4 or greater than or equal to the requested precision (i.e., max_digits)
|
|
383
|
+
// then we use exponential notation.
|
|
384
|
+
//
|
|
385
|
+
// But since "exp10" is the base-10 exponent corresponding to a mantissa in
|
|
386
|
+
// the range [0.1, 1), whereas the '%g' rules assume a mantissa in the range
|
|
387
|
+
// [1.0, 10), we need to adjust these parameters by 1.
|
|
388
|
+
if (exp10 <= -4 || exp10 > max_digits) {
|
|
389
|
+
// Use exponential format.
|
|
390
|
+
str.push_back(digits[0]);
|
|
391
|
+
if (digits.size() > 1) {
|
|
392
|
+
str.push_back('.');
|
|
393
|
+
str.append(digits.begin() + 1, digits.end());
|
|
394
|
+
}
|
|
395
|
+
char exp_buf[20];
|
|
396
|
+
sprintf(exp_buf, "e%+02d", exp10 - 1);
|
|
397
|
+
str += exp_buf;
|
|
398
|
+
} else {
|
|
399
|
+
// Use fixed format. We split this into two cases depending on whether
|
|
400
|
+
// the integer portion is non-zero or not.
|
|
401
|
+
if (exp10 > 0) {
|
|
402
|
+
if (exp10 >= digits.size()) {
|
|
403
|
+
str += digits;
|
|
404
|
+
for (int i = exp10 - digits.size(); i > 0; --i) {
|
|
405
|
+
str.push_back('0');
|
|
406
|
+
}
|
|
407
|
+
} else {
|
|
408
|
+
str.append(digits.begin(), digits.begin() + exp10);
|
|
409
|
+
str.push_back('.');
|
|
410
|
+
str.append(digits.begin() + exp10, digits.end());
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
str += "0.";
|
|
414
|
+
for (int i = exp10; i < 0; ++i) {
|
|
415
|
+
str.push_back('0');
|
|
416
|
+
}
|
|
417
|
+
str += digits;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return str;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Increment an unsigned integer represented as a string of ASCII digits.
|
|
424
|
+
static void IncrementDecimalDigits(string* digits) {
|
|
425
|
+
string::iterator pos = digits->end();
|
|
426
|
+
while (--pos >= digits->begin()) {
|
|
427
|
+
if (*pos < '9') { ++*pos; return; }
|
|
428
|
+
*pos = '0';
|
|
429
|
+
}
|
|
430
|
+
digits->insert(0, "1");
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
int ExactFloat::GetDecimalDigits(int max_digits, string* digits) const {
|
|
434
|
+
S2_DCHECK(is_normal());
|
|
435
|
+
// Convert the value to the form (bn * (10 ** bn_exp10)) where "bn" is a
|
|
436
|
+
// positive integer (BIGNUM).
|
|
437
|
+
BIGNUM* bn = BN_new();
|
|
438
|
+
int bn_exp10;
|
|
439
|
+
if (bn_exp_ >= 0) {
|
|
440
|
+
// The easy case: bn = bn_ * (2 ** bn_exp_)), bn_exp10 = 0.
|
|
441
|
+
S2_CHECK(BN_lshift(bn, bn_.get(), bn_exp_));
|
|
442
|
+
bn_exp10 = 0;
|
|
443
|
+
} else {
|
|
444
|
+
// Set bn = bn_ * (5 ** -bn_exp_) and bn_exp10 = bn_exp_. This is
|
|
445
|
+
// equivalent to the original value of (bn_ * (2 ** bn_exp_)).
|
|
446
|
+
BIGNUM* power = BN_new();
|
|
447
|
+
S2_CHECK(BN_set_word(power, -bn_exp_));
|
|
448
|
+
S2_CHECK(BN_set_word(bn, 5));
|
|
449
|
+
BN_CTX* ctx = BN_CTX_new();
|
|
450
|
+
S2_CHECK(BN_exp(bn, bn, power, ctx));
|
|
451
|
+
S2_CHECK(BN_mul(bn, bn, bn_.get(), ctx));
|
|
452
|
+
BN_CTX_free(ctx);
|
|
453
|
+
BN_free(power);
|
|
454
|
+
bn_exp10 = bn_exp_;
|
|
455
|
+
}
|
|
456
|
+
// Now convert "bn" to a decimal string.
|
|
457
|
+
char* all_digits = BN_bn2dec(bn);
|
|
458
|
+
S2_DCHECK(all_digits != nullptr);
|
|
459
|
+
BN_free(bn);
|
|
460
|
+
// Check whether we have too many digits and round if necessary.
|
|
461
|
+
int num_digits = strlen(all_digits);
|
|
462
|
+
if (num_digits <= max_digits) {
|
|
463
|
+
*digits = all_digits;
|
|
464
|
+
} else {
|
|
465
|
+
digits->assign(all_digits, max_digits);
|
|
466
|
+
// Standard "printf" formatting rounds ties to an even number. This means
|
|
467
|
+
// that we round up (away from zero) if highest discarded digit is '5' or
|
|
468
|
+
// more, unless all other discarded digits are zero in which case we round
|
|
469
|
+
// up only if the lowest kept digit is odd.
|
|
470
|
+
if (all_digits[max_digits] >= '5' &&
|
|
471
|
+
((all_digits[max_digits-1] & 1) == 1 ||
|
|
472
|
+
strpbrk(all_digits + max_digits + 1, "123456789") != nullptr)) {
|
|
473
|
+
// This can increase the number of digits by 1, but in that case at
|
|
474
|
+
// least one trailing zero will be stripped off below.
|
|
475
|
+
IncrementDecimalDigits(digits);
|
|
476
|
+
}
|
|
477
|
+
// Adjust the base-10 exponent to reflect the digits we have removed.
|
|
478
|
+
bn_exp10 += num_digits - max_digits;
|
|
479
|
+
}
|
|
480
|
+
OPENSSL_free(all_digits);
|
|
481
|
+
|
|
482
|
+
// Now strip any trailing zeros.
|
|
483
|
+
S2_DCHECK_NE((*digits)[0], '0');
|
|
484
|
+
string::iterator pos = digits->end();
|
|
485
|
+
while (pos[-1] == '0') --pos;
|
|
486
|
+
if (pos < digits->end()) {
|
|
487
|
+
bn_exp10 += digits->end() - pos;
|
|
488
|
+
digits->erase(pos, digits->end());
|
|
489
|
+
}
|
|
490
|
+
S2_DCHECK_LE(digits->size(), max_digits);
|
|
491
|
+
|
|
492
|
+
// Finally, we adjust the base-10 exponent so that the mantissa is a
|
|
493
|
+
// fraction in the range [0.1, 1) rather than an integer.
|
|
494
|
+
return bn_exp10 + digits->size();
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
string ExactFloat::ToUniqueString() const {
|
|
498
|
+
char prec_buf[20];
|
|
499
|
+
sprintf(prec_buf, "<%d>", prec());
|
|
500
|
+
return ToString() + prec_buf;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
ExactFloat& ExactFloat::operator=(const ExactFloat& b) {
|
|
504
|
+
if (this != &b) {
|
|
505
|
+
sign_ = b.sign_;
|
|
506
|
+
bn_exp_ = b.bn_exp_;
|
|
507
|
+
BN_copy(bn_.get(), b.bn_.get());
|
|
508
|
+
}
|
|
509
|
+
return *this;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
ExactFloat ExactFloat::operator-() const {
|
|
513
|
+
return CopyWithSign(-sign_);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
ExactFloat operator+(const ExactFloat& a, const ExactFloat& b) {
|
|
517
|
+
return ExactFloat::SignedSum(a.sign_, &a, b.sign_, &b);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
ExactFloat operator-(const ExactFloat& a, const ExactFloat& b) {
|
|
521
|
+
return ExactFloat::SignedSum(a.sign_, &a, -b.sign_, &b);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
ExactFloat ExactFloat::SignedSum(int a_sign, const ExactFloat* a,
|
|
525
|
+
int b_sign, const ExactFloat* b) {
|
|
526
|
+
if (!a->is_normal() || !b->is_normal()) {
|
|
527
|
+
// Handle zero, infinity, and NaN according to IEEE 754-2008.
|
|
528
|
+
if (a->is_nan()) return *a;
|
|
529
|
+
if (b->is_nan()) return *b;
|
|
530
|
+
if (a->is_inf()) {
|
|
531
|
+
// Adding two infinities with opposite sign yields NaN.
|
|
532
|
+
if (b->is_inf() && a_sign != b_sign) return NaN();
|
|
533
|
+
return Infinity(a_sign);
|
|
534
|
+
}
|
|
535
|
+
if (b->is_inf()) return Infinity(b_sign);
|
|
536
|
+
if (a->is_zero()) {
|
|
537
|
+
if (!b->is_zero()) return b->CopyWithSign(b_sign);
|
|
538
|
+
// Adding two zeros with the same sign preserves the sign.
|
|
539
|
+
if (a_sign == b_sign) return SignedZero(a_sign);
|
|
540
|
+
// Adding two zeros of opposite sign produces +0.
|
|
541
|
+
return SignedZero(+1);
|
|
542
|
+
}
|
|
543
|
+
S2_DCHECK(b->is_zero());
|
|
544
|
+
return a->CopyWithSign(a_sign);
|
|
545
|
+
}
|
|
546
|
+
// Swap the numbers if necessary so that "a" has the larger bn_exp_.
|
|
547
|
+
if (a->bn_exp_ < b->bn_exp_) {
|
|
548
|
+
using std::swap;
|
|
549
|
+
swap(a_sign, b_sign);
|
|
550
|
+
swap(a, b);
|
|
551
|
+
}
|
|
552
|
+
// Shift "a" if necessary so that both values have the same bn_exp_.
|
|
553
|
+
ExactFloat r;
|
|
554
|
+
if (a->bn_exp_ > b->bn_exp_) {
|
|
555
|
+
S2_CHECK(BN_lshift(r.bn_.get(), a->bn_.get(), a->bn_exp_ - b->bn_exp_));
|
|
556
|
+
a = &r; // The only field of "a" used below is bn_.
|
|
557
|
+
}
|
|
558
|
+
r.bn_exp_ = b->bn_exp_;
|
|
559
|
+
if (a_sign == b_sign) {
|
|
560
|
+
S2_CHECK(BN_add(r.bn_.get(), a->bn_.get(), b->bn_.get()));
|
|
561
|
+
r.sign_ = a_sign;
|
|
562
|
+
} else {
|
|
563
|
+
// Note that the BIGNUM documentation is out of date -- all methods now
|
|
564
|
+
// allow the result to be the same as any input argument, so it is okay if
|
|
565
|
+
// (a == &r) due to the shift above.
|
|
566
|
+
S2_CHECK(BN_sub(r.bn_.get(), a->bn_.get(), b->bn_.get()));
|
|
567
|
+
if (BN_is_zero(r.bn_.get())) {
|
|
568
|
+
r.sign_ = +1;
|
|
569
|
+
} else if (BN_is_negative(r.bn_.get())) {
|
|
570
|
+
// The magnitude of "b" was larger.
|
|
571
|
+
r.sign_ = b_sign;
|
|
572
|
+
BN_set_negative(r.bn_.get(), false);
|
|
573
|
+
} else {
|
|
574
|
+
// They were equal, or the magnitude of "a" was larger.
|
|
575
|
+
r.sign_ = a_sign;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
r.Canonicalize();
|
|
579
|
+
return r;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
void ExactFloat::Canonicalize() {
|
|
583
|
+
if (!is_normal()) return;
|
|
584
|
+
|
|
585
|
+
// Underflow/overflow occurs if exp() is not in [kMinExp, kMaxExp].
|
|
586
|
+
// We also convert a zero mantissa to signed zero.
|
|
587
|
+
int my_exp = exp();
|
|
588
|
+
if (my_exp < kMinExp || BN_is_zero(bn_.get())) {
|
|
589
|
+
set_zero(sign_);
|
|
590
|
+
} else if (my_exp > kMaxExp) {
|
|
591
|
+
set_inf(sign_);
|
|
592
|
+
} else if (!BN_is_odd(bn_.get())) {
|
|
593
|
+
// Remove any low-order zero bits from the mantissa.
|
|
594
|
+
S2_DCHECK(!BN_is_zero(bn_.get()));
|
|
595
|
+
int shift = BN_ext_count_low_zero_bits(bn_.get());
|
|
596
|
+
if (shift > 0) {
|
|
597
|
+
S2_CHECK(BN_rshift(bn_.get(), bn_.get(), shift));
|
|
598
|
+
bn_exp_ += shift;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
// If the mantissa has too many bits, we replace it by NaN to indicate
|
|
602
|
+
// that an inexact calculation has occurred.
|
|
603
|
+
if (prec() > kMaxPrec) {
|
|
604
|
+
set_nan();
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
ExactFloat operator*(const ExactFloat& a, const ExactFloat& b) {
|
|
609
|
+
int result_sign = a.sign_ * b.sign_;
|
|
610
|
+
if (!a.is_normal() || !b.is_normal()) {
|
|
611
|
+
// Handle zero, infinity, and NaN according to IEEE 754-2008.
|
|
612
|
+
if (a.is_nan()) return a;
|
|
613
|
+
if (b.is_nan()) return b;
|
|
614
|
+
if (a.is_inf()) {
|
|
615
|
+
// Infinity times zero yields NaN.
|
|
616
|
+
if (b.is_zero()) return ExactFloat::NaN();
|
|
617
|
+
return ExactFloat::Infinity(result_sign);
|
|
618
|
+
}
|
|
619
|
+
if (b.is_inf()) {
|
|
620
|
+
if (a.is_zero()) return ExactFloat::NaN();
|
|
621
|
+
return ExactFloat::Infinity(result_sign);
|
|
622
|
+
}
|
|
623
|
+
S2_DCHECK(a.is_zero() || b.is_zero());
|
|
624
|
+
return ExactFloat::SignedZero(result_sign);
|
|
625
|
+
}
|
|
626
|
+
ExactFloat r;
|
|
627
|
+
r.sign_ = result_sign;
|
|
628
|
+
r.bn_exp_ = a.bn_exp_ + b.bn_exp_;
|
|
629
|
+
BN_CTX* ctx = BN_CTX_new();
|
|
630
|
+
S2_CHECK(BN_mul(r.bn_.get(), a.bn_.get(), b.bn_.get(), ctx));
|
|
631
|
+
BN_CTX_free(ctx);
|
|
632
|
+
r.Canonicalize();
|
|
633
|
+
return r;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
bool operator==(const ExactFloat& a, const ExactFloat& b) {
|
|
637
|
+
// NaN is not equal to anything, not even itself.
|
|
638
|
+
if (a.is_nan() || b.is_nan()) return false;
|
|
639
|
+
|
|
640
|
+
// Since Canonicalize() strips low-order zero bits, all other cases
|
|
641
|
+
// (including non-normal values) require bn_exp_ to be equal.
|
|
642
|
+
if (a.bn_exp_ != b.bn_exp_) return false;
|
|
643
|
+
|
|
644
|
+
// Positive and negative zero are equal.
|
|
645
|
+
if (a.is_zero() && b.is_zero()) return true;
|
|
646
|
+
|
|
647
|
+
// Otherwise, the signs and mantissas must match. Note that non-normal
|
|
648
|
+
// values such as infinity have a mantissa of zero.
|
|
649
|
+
return a.sign_ == b.sign_ && BN_ucmp(a.bn_.get(), b.bn_.get()) == 0;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
int ExactFloat::ScaleAndCompare(const ExactFloat& b) const {
|
|
653
|
+
S2_DCHECK(is_normal() && b.is_normal() && bn_exp_ >= b.bn_exp_);
|
|
654
|
+
ExactFloat tmp = *this;
|
|
655
|
+
S2_CHECK(BN_lshift(tmp.bn_.get(), tmp.bn_.get(), bn_exp_ - b.bn_exp_));
|
|
656
|
+
return BN_ucmp(tmp.bn_.get(), b.bn_.get());
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
bool ExactFloat::UnsignedLess(const ExactFloat& b) const {
|
|
660
|
+
// Handle the zero/infinity cases (NaN has already been done).
|
|
661
|
+
if (is_inf() || b.is_zero()) return false;
|
|
662
|
+
if (is_zero() || b.is_inf()) return true;
|
|
663
|
+
// If the high-order bit positions differ, we are done.
|
|
664
|
+
int cmp = exp() - b.exp();
|
|
665
|
+
if (cmp != 0) return cmp < 0;
|
|
666
|
+
// Otherwise shift one of the two values so that they both have the same
|
|
667
|
+
// bn_exp_ and then compare the mantissas.
|
|
668
|
+
return (bn_exp_ >= b.bn_exp_ ?
|
|
669
|
+
ScaleAndCompare(b) < 0 : b.ScaleAndCompare(*this) > 0);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
bool operator<(const ExactFloat& a, const ExactFloat& b) {
|
|
673
|
+
// NaN is unordered compared to everything, including itself.
|
|
674
|
+
if (a.is_nan() || b.is_nan()) return false;
|
|
675
|
+
// Positive and negative zero are equal.
|
|
676
|
+
if (a.is_zero() && b.is_zero()) return false;
|
|
677
|
+
// Otherwise, anything negative is less than anything positive.
|
|
678
|
+
if (a.sign_ != b.sign_) return a.sign_ < b.sign_;
|
|
679
|
+
// Now we just compare absolute values.
|
|
680
|
+
return (a.sign_ > 0) ? a.UnsignedLess(b) : b.UnsignedLess(a);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
ExactFloat fabs(const ExactFloat& a) {
|
|
684
|
+
return abs(a);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
ExactFloat abs(const ExactFloat& a) {
|
|
688
|
+
return a.CopyWithSign(+1);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
ExactFloat fmax(const ExactFloat& a, const ExactFloat& b) {
|
|
692
|
+
// If one argument is NaN, return the other argument.
|
|
693
|
+
if (a.is_nan()) return b;
|
|
694
|
+
if (b.is_nan()) return a;
|
|
695
|
+
// Not required by IEEE 754, but we prefer +0 over -0.
|
|
696
|
+
if (a.sign_ != b.sign_) {
|
|
697
|
+
return (a.sign_ < b.sign_) ? b : a;
|
|
698
|
+
}
|
|
699
|
+
return (a < b) ? b : a;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
ExactFloat fmin(const ExactFloat& a, const ExactFloat& b) {
|
|
703
|
+
// If one argument is NaN, return the other argument.
|
|
704
|
+
if (a.is_nan()) return b;
|
|
705
|
+
if (b.is_nan()) return a;
|
|
706
|
+
// Not required by IEEE 754, but we prefer -0 over +0.
|
|
707
|
+
if (a.sign_ != b.sign_) {
|
|
708
|
+
return (a.sign_ < b.sign_) ? a : b;
|
|
709
|
+
}
|
|
710
|
+
return (a < b) ? a : b;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
ExactFloat fdim(const ExactFloat& a, const ExactFloat& b) {
|
|
714
|
+
// This formulation has the correct behavior for NaNs.
|
|
715
|
+
return (a <= b) ? 0 : (a - b);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
ExactFloat ceil(const ExactFloat& a) {
|
|
719
|
+
return a.RoundToPowerOf2(0, ExactFloat::kRoundTowardPositive);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
ExactFloat floor(const ExactFloat& a) {
|
|
723
|
+
return a.RoundToPowerOf2(0, ExactFloat::kRoundTowardNegative);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
ExactFloat trunc(const ExactFloat& a) {
|
|
727
|
+
return a.RoundToPowerOf2(0, ExactFloat::kRoundTowardZero);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
ExactFloat round(const ExactFloat& a) {
|
|
731
|
+
return a.RoundToPowerOf2(0, ExactFloat::kRoundTiesAwayFromZero);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
ExactFloat rint(const ExactFloat& a) {
|
|
735
|
+
return a.RoundToPowerOf2(0, ExactFloat::kRoundTiesToEven);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
template <class T>
|
|
739
|
+
T ExactFloat::ToInteger(RoundingMode mode) const {
|
|
740
|
+
using std::numeric_limits;
|
|
741
|
+
static_assert(sizeof(T) <= sizeof(uint64), "max 64 bits supported");
|
|
742
|
+
static_assert(numeric_limits<T>::is_signed, "only signed types supported");
|
|
743
|
+
const int64 kMinValue = numeric_limits<T>::min();
|
|
744
|
+
const int64 kMaxValue = numeric_limits<T>::max();
|
|
745
|
+
|
|
746
|
+
ExactFloat r = RoundToPowerOf2(0, mode);
|
|
747
|
+
if (r.is_nan()) return kMaxValue;
|
|
748
|
+
if (r.is_zero()) return 0;
|
|
749
|
+
if (!r.is_inf()) {
|
|
750
|
+
// If the unsigned value has more than 63 bits it is always clamped.
|
|
751
|
+
if (r.exp() < 64) {
|
|
752
|
+
int64 value = BN_ext_get_uint64(r.bn_.get()) << r.bn_exp_;
|
|
753
|
+
if (r.sign_ < 0) value = -value;
|
|
754
|
+
return max(kMinValue, min(kMaxValue, value));
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
return (r.sign_ < 0) ? kMinValue : kMaxValue;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
long lrint(const ExactFloat& a) {
|
|
761
|
+
return a.ToInteger<long>(ExactFloat::kRoundTiesToEven);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
long long llrint(const ExactFloat& a) {
|
|
765
|
+
return a.ToInteger<long long>(ExactFloat::kRoundTiesToEven);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
long lround(const ExactFloat& a) {
|
|
769
|
+
return a.ToInteger<long>(ExactFloat::kRoundTiesAwayFromZero);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
long long llround(const ExactFloat& a) {
|
|
773
|
+
return a.ToInteger<long long>(ExactFloat::kRoundTiesAwayFromZero);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
ExactFloat copysign(const ExactFloat& a, const ExactFloat& b) {
|
|
777
|
+
return a.CopyWithSign(b.sign_);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
ExactFloat frexp(const ExactFloat& a, int* exp) {
|
|
781
|
+
if (!a.is_normal()) {
|
|
782
|
+
// If a == 0, exp should be zero. If a.is_inf() or a.is_nan(), exp is not
|
|
783
|
+
// defined but the glibc implementation returns zero.
|
|
784
|
+
*exp = 0;
|
|
785
|
+
return a;
|
|
786
|
+
}
|
|
787
|
+
*exp = a.exp();
|
|
788
|
+
return ldexp(a, -a.exp());
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
ExactFloat ldexp(const ExactFloat& a, int exp) {
|
|
792
|
+
if (!a.is_normal()) return a;
|
|
793
|
+
|
|
794
|
+
// To prevent integer overflow, we first clamp "exp" so that
|
|
795
|
+
// (kMinExp - 1) <= (a_exp + exp) <= (kMaxExp + 1).
|
|
796
|
+
int a_exp = a.exp();
|
|
797
|
+
exp = min(ExactFloat::kMaxExp + 1 - a_exp,
|
|
798
|
+
max(ExactFloat::kMinExp - 1 + a_exp, exp));
|
|
799
|
+
|
|
800
|
+
// Now modify the exponent and check for overflow/underflow.
|
|
801
|
+
ExactFloat r = a;
|
|
802
|
+
r.bn_exp_ += exp;
|
|
803
|
+
r.Canonicalize();
|
|
804
|
+
return r;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
ExactFloat scalbln(const ExactFloat& a, long exp) {
|
|
808
|
+
// Clamp the exponent to the range of "int" in order to avoid truncation.
|
|
809
|
+
exp = max(static_cast<long>(INT_MIN), min(static_cast<long>(INT_MAX), exp));
|
|
810
|
+
return ldexp(a, exp);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
int ilogb(const ExactFloat& a) {
|
|
814
|
+
if (a.is_zero()) return FP_ILOGB0;
|
|
815
|
+
if (a.is_inf()) return INT_MAX;
|
|
816
|
+
if (a.is_nan()) return FP_ILOGBNAN;
|
|
817
|
+
// a.exp() assumes the significand is in the range [0.5, 1).
|
|
818
|
+
return a.exp() - 1;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
ExactFloat logb(const ExactFloat& a) {
|
|
822
|
+
if (a.is_zero()) return ExactFloat::Infinity(-1);
|
|
823
|
+
if (a.is_inf()) return ExactFloat::Infinity(+1); // Even if a < 0.
|
|
824
|
+
if (a.is_nan()) return a;
|
|
825
|
+
// exp() assumes the significand is in the range [0.5,1).
|
|
826
|
+
return ExactFloat(a.exp() - 1);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
ExactFloat ExactFloat::Unimplemented() {
|
|
830
|
+
S2_LOG(FATAL) << "Unimplemented ExactFloat method called";
|
|
831
|
+
return NaN();
|
|
832
|
+
}
|